﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Windows.Threading;
using VisualTest2.Drawings;

namespace VisualTest2
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {

        bool isAntialised = true;

        int METOD_POLYLINE = 1;
        int METOD_FRAMEWORKELEMENT = 2;
        int METOD_LINEGEOMETRYGROUP = 3;
        int METOD_PATH = 4;
        int METOD_VISUALHOST = 5;
        int current_Method = 3;

        PoliElement poli = null;
        VisualHost visualHost = null;
        Path path = null;

        int POINT_COUNT = 500;
        Line line = new Line();
        Line line2 = new Line();
        PointCollection collection;
        Stopwatch watch = new Stopwatch();
        double oldMilis = 0;
        public Window1()
        {
            InitializeComponent();
            watch.Start();

            line.IsHitTestVisible = false;
            line2.IsHitTestVisible = false;

            comboBox1.Items.Add("METOD_POLYLINE");
            comboBox1.Items.Add("METOD_FRAMEWORKELEMENT");
            comboBox1.Items.Add("METOD_LINEGEOMETRYGROUP");
            comboBox1.Items.Add("METOD_PATH");
            comboBox1.Items.Add("METOD_VISUALHOST");
            comboBox1.SelectedIndex = current_Method - 1;
        }

        #region GridCenter Events
        private void gridCenter_MouseMove(object sender, MouseEventArgs e)
        {
            if (gridCenter.IsLoaded)
            {
                if (watch.Elapsed.TotalMilliseconds - oldMilis > 40)
                {
                    object aa = polyLine.GetValue(Polyline.FillProperty);
                    object bb = polyLine.GetValue(Polyline.StrokeProperty);
                    double mousePosX = Mouse.GetPosition(sender as Grid).X;
                    Point poliPoint = new Point(10, 10);
                    if (current_Method == METOD_POLYLINE)
                    {
                        poliPoint = PointOperations.getPolylinePoint(collection, mousePosX);
                    }
                    else if (current_Method == METOD_FRAMEWORKELEMENT)
                    {
                        if (poli != null && poli.PointCollection != null)
                        {
                            poliPoint = PointOperations.getPolylinePoint(poli.PointCollection, mousePosX);
                        }
                    }
                    else if (current_Method == METOD_LINEGEOMETRYGROUP)
                    {
                        if (collection != null)
                        {
                            poliPoint = PointOperations.getPolylinePoint(collection, mousePosX);
                        }

                    }
                    else if (current_Method == METOD_VISUALHOST)
                    {
                        if (visualHost != null && visualHost.collection != null)
                        {
                            poliPoint = PointOperations.getPolylinePoint(visualHost.collection, mousePosX);
                        }
                    }
                    else if (current_Method == METOD_PATH)
                    {

                        if (collection != null)
                        {
                            poliPoint = PointOperations.getPolylinePoint(collection, mousePosX);
                        }
                    }
                    else
                    {
                        poliPoint = new Point(Mouse.GetPosition(sender as Grid).X, mousePosX);
                    }

                    line.X1 = (int)poliPoint.X;
                    line.X2 = (int)poliPoint.X;
                    line.Y1 = 0;
                    line.Y2 = (int)gridCenter.ActualHeight;

                    line2.X1 = 0;
                    line2.X2 = (int)gridCenter.ActualWidth;
                    line2.Y1 = (int)poliPoint.Y;
                    line2.Y2 = (int)poliPoint.Y;
                    oldMilis = watch.Elapsed.TotalMilliseconds;
                }
                else
                {
                    //Debug.WriteLine("Discarded");
                }
            }
        }
        private void initLineSpec()
        {
            line.Stroke = Brushes.Blue;
            line.StrokeThickness = 1;
            line2.Stroke = Brushes.Blue;
            line2.StrokeThickness = 1;
            DoubleCollection dashes = new DoubleCollection();
            dashes.Add(8);
            dashes.Add(8);
            //line2.StrokeDashArray = dashes;
            line2.StrokeDashCap = PenLineCap.Round;
            //line.StrokeDashArray = dashes;
            line.StrokeDashCap = PenLineCap.Round;
        }

        private void gridCenter_MouseEnter(object sender, MouseEventArgs e)
        {
            if (gridCenter.IsLoaded)
            {
                initLineSpec();
            }
        }
        private void gridCenter_MouseLeave(object sender, MouseEventArgs e)
        {
            line.Stroke = Brushes.Transparent;
            line2.Stroke = Brushes.Transparent;
        }
        private void gridCenter_Loaded(object sender, RoutedEventArgs e)
        {
            refreshGraph();
            gridCenter.Children.Add(line);
            gridCenter.Children.Add(line2);
        }
        #endregion
        private void refreshPoli(Size newSize)
        {
            collection = new PointCollection();
            Random r = new Random();

            double ratio = newSize.Width / POINT_COUNT;
            collection.Add(new Point(0, gridCenter.ActualHeight));
            for (int i = 1; i < POINT_COUNT; i++)
            {
                double randY = Math.Round((r.NextDouble() * (gridCenter.ActualHeight)), 0);
                if (randY <= 16)
                {
                    randY += 10;
                }
                collection.Add(new Point(Math.Round((i * ratio), 0), randY));
            }
            collection.Add(new Point(gridCenter.ActualWidth, gridCenter.ActualHeight));

            polyLine.Points = collection;
        }
        private void addLineGeometries()
        {
            double w = gridCenter.ActualWidth;
            double h = gridCenter.ActualHeight;
            PointOperations ops = new PointOperations();
            collection = ops.createRandomCollection(new Size(w, h), POINT_COUNT);
            VisualUtilities.addLineGeometries(collection, connectors);
        }



        private volatile object lockObject = new object();
        private void refreshGraph()
        {
            lock (lockObject)
            {
                if (current_Method != METOD_FRAMEWORKELEMENT)
                {
                    gridCenter.Children.Remove(poli);
                }
                if (current_Method != METOD_POLYLINE)
                {
                    polyLine.Visibility = Visibility.Collapsed;
                }

                gridCenter.Children.Remove(path);
                gridCenter.Children.Remove(visualHost);
                connectors.Children.Clear();

                if (current_Method == METOD_POLYLINE)
                {
                    if (isAntialised)
                    {
                        polyLine.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
                    }
                    polyLine.SetValue(RenderOptions.CachingHintProperty, CachingHint.Cache);
                    polyLine.IsHitTestVisible = false;
                    polyLine.Visibility = Visibility.Visible;
                    refreshPoli(gridCenter.RenderSize);
                }
                else if (current_Method == METOD_FRAMEWORKELEMENT)
                {

                    if (gridCenter.Children.Contains(poli))
                    {
                        PointOperations ops = new PointOperations();
                        poli.PointCollection = ops.createRandomCollection(new Size(gridCenter.ActualWidth, gridCenter.ActualHeight), POINT_COUNT);
                        poli.InvalidateVisual();

                    }
                    else
                    {
                        PointOperations ops = new PointOperations();
                        poli = new PoliElement(POINT_COUNT, new Size(gridCenter.ActualWidth, gridCenter.ActualHeight));
                        poli.PointCollection = ops.createRandomCollection(new Size(gridCenter.ActualWidth, gridCenter.ActualHeight), POINT_COUNT);
                        poli.IsHitTestVisible = false;
                        gridCenter.Children.Add(poli);
                    }
                    if (isAntialised)
                    {
                        poli.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
                    }
                }
                else if (current_Method == METOD_LINEGEOMETRYGROUP)
                {
                    if (isAntialised)
                    {
                        connectorsPath.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
                    }
                    connectors.Children.Clear();
                    addLineGeometries();
                }
                else if (current_Method == METOD_PATH)
                {
                    collection = new PointOperations().
                        createRandomCollection(new Size(gridCenter.ActualWidth, gridCenter.ActualHeight), POINT_COUNT);
                    path = VisualUtilities.CreatePolygonPath(collection, isAntialised);

                    gridCenter.Children.Add(path);
                }
                else if (current_Method == METOD_VISUALHOST)
                {

                    visualHost = new VisualHost(new PointOperations().createRandomCollection(new Size(gridCenter.ActualWidth, gridCenter.ActualHeight), POINT_COUNT));
                    visualHost.IsHitTestVisible = false;
                    if (isAntialised)
                    {
                        visualHost.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
                    }
                    gridCenter.Children.Add(visualHost);
                }
            }
        }

        DispatcherTimer timer2 = null, timer = null;
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            if (timer2 == null)
            {
                timer2 = new DispatcherTimer(DispatcherPriority.ContextIdle);
                timer2.Interval = new TimeSpan(0, 0, 0, 0, 100);
                timer2.Tick += new EventHandler(delegate(object s, EventArgs a)
                {
                    refreshGraph();
                });
                timer2.Start();
                button2.Content = "Stop";
            }
            else if (timer2.IsEnabled)
            {
                button2.Content = "Start";
                timer2.Stop();
            }
            else
            {
                button2.Content = "Stop";
                timer2.Start();
            }
        }
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            if (timer == null)
            {
                timer = new DispatcherTimer(DispatcherPriority.DataBind);
                timer.Interval = new TimeSpan(0, 0, 0, 0, 10);
                timer.Tick += new EventHandler(delegate(object s, EventArgs a)
                {
                    line.X1 += 1;
                    line.X2 += 1;
                });
                timer.Start();
                button1.Content = "Stop Line Timer";
            }
            else if (timer.IsEnabled)
            {
                button1.Content = "Start Line Timer";
                timer.Stop();
            }
            else
            {
                button1.Content = "Stop Line Timer";
                timer.Start();
            }
        }

        private void gridCenter_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if ((sender as Grid).IsLoaded)
            {
                refreshGraph();
            }
        }
        private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (gridCenter.IsLoaded)
            {
                current_Method = comboBox1.SelectedIndex + 1;
                refreshGraph();
            }
        }
    }
}
